home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  24.0 KB  |  1,332 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     edit.c
  5.  
  6.     DESCRIPTION
  7.     Everything for editing like DEL, BS, INDENT, DELINE, INSLINE, ...
  8.  
  9.     NOTES
  10.  
  11.     BUGS
  12.  
  13.     TODO
  14.  
  15.     EXAMPLES
  16.  
  17.     SEE ALSO
  18.  
  19.     INDEX
  20.  
  21.     HISTORY
  22.     14. Nov 1992    ada created
  23.  
  24. ******************************************************************************/
  25.  
  26. /**************************************
  27.         Includes
  28. **************************************/
  29. #include "defs.h"
  30. #include "clipboard.h"
  31. #define MYDEBUG     0
  32. #include <debug.h>
  33.  
  34.  
  35. /**************************************
  36.         Globale Variable
  37. **************************************/
  38.  
  39.  
  40. /**************************************
  41.       Interne Defines & Strukturen
  42. **************************************/
  43.  
  44.  
  45. /**************************************
  46.         Interne Variable
  47. **************************************/
  48.  
  49.  
  50. /**************************************
  51.        Interne Prototypes
  52. **************************************/
  53. Prototype void do_bs         (void);
  54. Prototype void do_del         (void);
  55. Prototype void do_remeol     (void);
  56. Prototype void do_split      (void);
  57. Prototype int  do_join         (void);
  58. Prototype void do_reformat   (int);
  59. Prototype void do_insertmode (void);
  60. Prototype void do_insline    (void);
  61. Prototype void do_deline     (void);
  62. Prototype void do_tlate      (void);
  63. Prototype void do_justify    (void);
  64. Prototype void do_unjustify  (void);
  65. Prototype void do_indent     (void);
  66. Prototype void do_inslines   (void);
  67. Prototype void do_delete     (void);
  68. Prototype void do_delines    (void);
  69. Prototype void do_undeline   (void);
  70. Prototype void do_space      (void);
  71. Prototype void do_clipins    (void);
  72. Prototype void do_return     (void);
  73.  
  74.  
  75. void do_bs (void)
  76. {
  77.     ED     * ep  = Ep;
  78.     RP     * rp  = ep->win->RPort;
  79.     WORD   i,
  80.        col = ep->column;
  81.     Column right;
  82.     BOOL   is_bs = (av[0][0] == 'b');
  83.  
  84.     if ((Current[col] && !is_bs) || (col && is_bs))
  85.     {
  86.     if (is_bs)
  87.     {
  88.         movmem (Current + col, Current + col - 1, Clen - col + 1);
  89.  
  90.         col --;
  91.         ep->column --;
  92.  
  93.     } else
  94.         movmem (Current + col + 1, Current + col, Clen - col);
  95.  
  96.     Clen --;
  97.  
  98.     i = ep->line;
  99.     right = ep->topcolumn + Columns;
  100.  
  101.     if (!Nsu) {                         /* PATCH_NULL [09-Dec-92] : line added */
  102.         if (col < ep->topcolumn)
  103.         {
  104.         text_adjust (FALSE);
  105.         } else
  106.         {
  107.         if (is_inblock (i, right) & BP_INSIDE)
  108.         {
  109.             SetAPen (rp, BLOCK_FPEN);
  110.             SetBPen (rp, BLOCK_BPEN);
  111.         } else
  112.         {
  113.             SetAPen (rp, TEXT_FPEN);
  114.             SetBPen (rp, TEXT_BPEN);
  115.         }
  116.  
  117.         SetWrMsk (rp, BLOCK_MASK);
  118.  
  119.         i -= ep->topline;
  120.  
  121.         ScrollRaster(rp, Xsize, 0,
  122.             COL(col - ep->topcolumn),
  123.             ROW(i),
  124.             Xpixs,
  125.             ROW(i + 1) - 1
  126.         );
  127.  
  128.         if (ep->win->WLayer->Flags & LAYERREFRESH)
  129.             OptimizedRefresh (ep);
  130.         else if (Clen >= right)
  131.         {
  132.             right --;
  133.  
  134.             Move (rp, COLT(right - ep->topcolumn), ROWT(i));
  135.             Text (rp, Current + right, 1);
  136.         }
  137.         }
  138.     } /* if !Nsu */             /* PATCH_NULL [09-Dec-92] : line added */
  139.  
  140.     if (!globalflags.Comlinemode && ep->config.wordwrap)
  141.         do_reformat(0);
  142.     } else
  143.     {
  144.     globalflags.Abortcommand = 1;
  145.     }
  146. } /* do_bs */
  147.  
  148.  
  149. void do_remeol (void)
  150. {
  151.     Current[Clen = Ep->column] = 0;
  152.  
  153.     text_sync ();
  154.     text_redisplaycurrline ();
  155. } /* do_remeol */
  156.  
  157.  
  158. void do_split (void)              /* split line in two at cursor pos */
  159. {
  160.     UBYTE buf[MAXLINELEN];
  161.     ED    * ep           = Ep;
  162.     RP    * rp           = ep->win->RPort;
  163.     char  onLastLine;
  164.  
  165.     strcpy ((char *)buf, (char *)Current+ep->column);
  166.     Current[Clen = ep->column] = '\0';
  167.  
  168.     text_sync ();
  169.  
  170.     SetAPen (rp, TEXT_BPEN);
  171.     SetWrMsk (rp, 0xFF);
  172.  
  173.     if (!Nsu)
  174.     RectFill (rp, COL(0), ROW(ep->line-ep->topline),
  175.            Xpixs, ROW(ep->line-ep->topline+1)-1);
  176.  
  177.     SetAPen (rp, TEXT_FPEN);
  178.  
  179.     text_displayseg (ep->line - ep->topline, 1);
  180.  
  181.     onLastLine = (ep->line == ep->lines-1);
  182.     do_downadd ();
  183.  
  184.     if (!onLastLine)
  185.     do_insline ();
  186.  
  187.     strcpy ((char *)Current, (char *)buf);
  188.     Clen = strlen ((char *)Current);
  189.  
  190.     text_sync ();
  191.     text_displayseg (ep->line - ep->topline, 1);
  192.  
  193.     do_up ();
  194. } /* do_split */
  195.  
  196.  
  197. int do_join (void)
  198. {
  199.     int   i = Clen, j;
  200.     ED * ep = Ep;
  201.  
  202.     /* Check if there is a line below and the length of both lines */
  203.     if (ep->line + 1 < ep->lines &&
  204.         LINELEN(ep,ep->line+1)+i <= MAXLINELEN-2)
  205.     {
  206.     /* Add a space */
  207.     if (i && Current[i-1] != ' ')
  208.         Current[i++] = ' ';
  209.  
  210.     /* Copy the line */
  211.     strcpy((char *)Current+i, GETTEXT(ep,ep->line+1));
  212.  
  213.     /* Find first nonspace */
  214.     for (j = i; Current[j] == ' '; ++j);
  215.     /* Find last space */
  216.     for (; i >= 0 && Current[i] == ' '; --i);
  217.  
  218.     /* Too many spaces ? */
  219.     if (j > i+2)
  220.         movmem (Current+j, Current+i+2, strlen((char *)Current+j)+1);
  221.  
  222.     /* new length */
  223.     Clen = strlen ((char *)Current);
  224.  
  225.     /* redisplay */
  226.     text_sync ();
  227.     text_displayseg (ep->line - ep->topline, 1);
  228.  
  229.     i = text_lineno ();
  230.  
  231.     do_down ();
  232.     do_deline ();
  233.  
  234.     if (i != text_lineno ())
  235.         do_up ();
  236.  
  237.     return(1);
  238.     }
  239.  
  240.     return(0);
  241. } /* do_join */
  242.  
  243.  
  244. /*
  245.  * n == -1  :    force reformat entire paragraph
  246.  * n ==  0  :    only until line equalizes (from text_write())
  247.  *
  248.  * What is a paragraph?   A paragraph ends whenever the left justification
  249.  * gets larger, or on a blank line.
  250.  */
  251.  
  252. void do_reformat (int n)
  253. {
  254.     char * str;
  255.     ED     * ep = Ep;
  256.     RP     * rp = ep->win->RPort;
  257.     int    nlok;   /* Next Line ok ? */
  258.     int    lnsc;   /* LastNS of Current */
  259.     int    fnst;   /* FirstNS of next Line */
  260.     int    fnsc;   /* FirstNS of Current */
  261.     int    column  = ep->column;
  262.     int    srow    = ep->line;
  263.     int    crow    = srow;
  264.     int    erow    = srow;
  265.     WORD   dins    = 0;     /* relative insert lines/delete lines    */
  266.     char   moded   = 0;     /* any modifications done at all?    */
  267.     char   checked = 0;     /* for cursor positioning.        */
  268.     Line   old_top;
  269.  
  270.     if (ep->config.margin == 0)
  271.     ep->config.margin = 75;
  272.  
  273.     Nsu ++;
  274.  
  275.     old_top = ep->topline;
  276.  
  277.     for (;;)
  278.     {
  279.     str = GETTEXT(ep,ep->line+1);
  280.     fnst = 0;
  281.     fnsc = firstns((char *)Current);
  282.     nlok = (ep->line + 1 < ep->lines && fnsc >= (fnst=firstns(str)));
  283.     if (ep->config.wwcol >= 0)
  284.         fnst = fnsc = ep->config.wwcol;
  285.     if (nlok && str[0] == 0)
  286.         nlok = 0;
  287.     lnsc = lastns((char *)Current);
  288.     if (lnsc < ep->config.margin)
  289.     {    /* space at end of line for marg-lnsc-2 letter word   */
  290.         if (nlok == 0)        /* but no more data to joinup   */
  291.         break;          /* done */
  292.         if (ep->config.margin - lnsc - 2 >= wordlen(str+fnst))
  293.         {
  294.         ep->column = 0;
  295.         Clen = lastns((char *)Current);
  296.         if (Current[Clen])
  297.             ++Clen;
  298.         moded = 1;
  299.         --dins;
  300.         if (do_join())
  301.             continue;
  302.         ++dins;
  303.  
  304.         error ("reformat:\nMargin too big");
  305.         break;
  306.         }
  307.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  308.         break;
  309.         do_down ();
  310.         erow = ep->line;
  311.         continue;
  312.     }
  313.                 /* no space, need to split    */
  314.                 /* find start of prev word    */
  315.     for (;;)
  316.     {
  317.         int i = lnsc;
  318.         while (i && Current[i] != ' ')
  319.         --i;
  320.         lnsc = i;
  321.         if (i >= ep->config.margin)
  322.         {
  323.         while (i && Current[i] == ' ')
  324.             --i;
  325.         if (i < ep->config.margin)
  326.             break;
  327.         lnsc = i;
  328.         } else
  329.         break;
  330.     }
  331.  
  332.     /* Word too long */
  333.     if (wordlen((char *)Current+lnsc) >= ep->config.margin)
  334.     {
  335.         error ("reformat:\nWord too long");
  336.         break;
  337.     }
  338.  
  339.     if (lnsc)
  340.     {          /* ok to split at word          */
  341.         ++lnsc;
  342.         ++dins;
  343.         ep->column = lnsc;
  344.         do_split (); /* Split at point LNSC          */
  345.         do_down ();          /* must insert proper amount?   */
  346.         {
  347.         int indent = (nlok == 0) ? fnsc : fnst;
  348.         if (ep->config.wwcol >= 0)
  349.             indent = ep->config.wwcol;
  350.         if (!checked)
  351.         {
  352.             checked = 1;
  353.             if (lnsc <= column)
  354.             {    /* if split before cursor   */
  355.             column = column - ep->column + indent;
  356.             ++crow;
  357.             }
  358.         }
  359.         if (Clen + indent < 253)
  360.         {
  361.             movmem(Current, Current + indent,
  362.                 strlen((char *)Current)+1);
  363.             setmem(Current, indent, ' ');
  364.             Clen += indent;
  365.         }
  366.         }
  367.         erow = ep->line;
  368.         continue;
  369.     }
  370.  
  371.     if (n == 0)
  372.         break;
  373.  
  374.     do_down ();
  375.     }
  376.  
  377.     if (column < 0 || column > 200)
  378.     column = 0;
  379.     if (srow >= ep->lines)
  380.     {
  381.     /* srow = ep->lines - 1; dead assign */
  382.     goto ra;
  383.     }
  384.  
  385.     Nsu --;
  386.  
  387.     if (old_top != ep->topline)
  388.     {
  389.     scroll_display (0, ep->topline-old_top,
  390.         ep->topcolumn, ep->topline,
  391.         ep->topcolumn + Columns, ep->topline + Lines);
  392.     }
  393.  
  394.     if (dins || srow < ep->topline || srow >= ep->topline + Lines)
  395.     {
  396. ra:
  397.     text_sync ();
  398.  
  399.     ep->line = crow;
  400.     ep->column = column;
  401.  
  402.     text_load ();
  403.  
  404.     text_adjust (TRUE);
  405.     } else
  406.     {
  407.     text_sync ();
  408.  
  409.     ep->line = crow;
  410.     ep->column = column;
  411.  
  412.     text_load ();
  413.  
  414.     if (erow != srow)
  415.     {
  416.         if (!text_adjust (FALSE))
  417.         {
  418.         if (erow - ep->topline > Lines)
  419.             erow = ep->topline + Lines;
  420.  
  421.         SetAPen(rp, TEXT_BPEN);
  422.         SetWrMsk (rp, 0xFF);
  423.  
  424.         RectFill(rp, COL(0), ROW(srow - ep->topline),
  425.             Xpixs, ROW(erow - ep->topline + 1)-1);
  426.  
  427.         SetAPen(rp, TEXT_FPEN);
  428.  
  429.         text_displayseg(srow - ep->topline, erow - srow + 1);
  430.         }
  431.     } else
  432.     {
  433.         if (moded)
  434.         text_redisplaycurrline ();
  435.     }
  436.     }
  437.     if (column > Clen)
  438.     {
  439.     setmem(Current+Clen, column - Clen, ' ');
  440.     Current[column] = 0;
  441.     }
  442.     ep->column = column;
  443. } /* do_reformat */
  444.  
  445.  
  446. void do_insline (void)
  447. {
  448.     LINE ptr;
  449.     ED *ep = Ep;
  450.  
  451.     ep->modified = 1;
  452.  
  453.     text_sync ();
  454.  
  455.     if (makeroom (32))
  456.     {
  457.     ptr = allocline (1);
  458.  
  459.     bmovl(ep->list+ep->line, ep->list+ep->line+1,ep->lines-ep->line);
  460.     SETLINE(ep,ep->line,ptr);
  461.  
  462.     ep->lines ++;
  463.  
  464.     if (ActualBlock.ep == ep)
  465.     {
  466.         if (ep->line <= ActualBlock.start_line)
  467.         ActualBlock.start_line ++;
  468.         if (ep->line <= ActualBlock.end_line)
  469.         ActualBlock.end_line ++;
  470.     }
  471.     } else
  472.     {
  473.     nomemory ();
  474.     }
  475.  
  476.     text_load ();
  477.  
  478.     if (Nsu == 0)
  479.     {
  480.     scroll_display (0, -1, 0, ep->line, MAXLINELEN, ep->topline+Lines);
  481.     text_displayseg (ep->line - ep->topline, 1);
  482.     }
  483. } /* do_insline */
  484.  
  485.  
  486. void do_deline (void)
  487. {
  488.     int delline, eline;
  489.     ED *ep = Ep;
  490.  
  491.     /* store line for later UNDO */
  492.     strcpy ((char *)Deline, (char *)Current);
  493.  
  494.     if (ep->lines > 1)
  495.     {
  496.     ep->modified = 1;
  497.  
  498.     text_sync ();
  499.  
  500.     /* remove line */
  501.     freeline (GETLINE(ep,ep->line));
  502.     bmovl (ep->list+ep->line+1, ep->list+ep->line, ep->lines-ep->line-1);
  503.  
  504.     /* adjust block */
  505.     if (ActualBlock.ep == ep)
  506.     {
  507.         if (ep->line < ActualBlock.start_line)
  508.         ActualBlock.start_line --;
  509.  
  510.         if (ep->line <= ActualBlock.end_line)
  511.         ActualBlock.end_line --;
  512.     }
  513.  
  514.     /* remember line we deleted */
  515.     delline = ep->line;
  516.  
  517.     /* line was last one */
  518.     if (ep->line >= --ep->lines)
  519.     {
  520.         /* move up one line */
  521.         --ep->line;
  522.  
  523.         /* get the line into current */
  524.         text_load ();
  525.  
  526.         /* line now below topline ? */
  527.         if (ep->line < ep->topline)
  528.         {
  529.         /* update screen if allowed */
  530.         if (!Nsu)
  531.         {
  532.             /* find new position */
  533.             ep->topline = ep->line - (Lines>>1);
  534.  
  535.             if (ep->topline < 0)
  536.             ep->topline = 0;
  537.  
  538.             text_redisplay ();
  539.         }
  540.  
  541.         return;
  542.         }
  543.     }
  544.  
  545.     /* get line */
  546.     text_load ();
  547.  
  548.     /* update display */
  549.     if (!Nsu)
  550.     {
  551.         eline = ep->topline + Lines - 1;
  552.  
  553.         if (ep->lines < eline)
  554.         eline = ep->lines +1;
  555.  
  556.         scroll_display (0, 1, ep->topcolumn, delline,
  557.                   ep->topcolumn+Columns-1, eline);
  558.     }
  559.     } else
  560.     {
  561.     /* no more lines in the text */
  562.     do_firstcolumn ();
  563.     do_remeol ();
  564.     ep->modified = 0;
  565.     }
  566. } /* do_deline */
  567.  
  568.  
  569. void do_tlate (void)
  570. {
  571.     UBYTE * ptr = av[1];
  572.     ED      * ep    = Ep;
  573.     UBYTE   c    = Current[ep->column];
  574.  
  575.     if (c == 0)
  576.     c = ' ';
  577.  
  578.     switch (*ptr)
  579.     {
  580.     case '+':
  581.         c += strtol ((char *)ptr+1, NULL, 0);
  582.         break;
  583.  
  584.     case '-':
  585.         c -= strtol ((char *)ptr+1, NULL, 0);
  586.         break;
  587.  
  588.     case '"':
  589.         c = ptr[1];
  590.         break;
  591.  
  592.     case 'u':
  593.     case 'U':
  594.         c = toupper (c);
  595.         break;
  596.  
  597.     case 'l':
  598.     case 'L':
  599.         c = tolower (c);
  600.         break;
  601.  
  602.     default:
  603.         c = strtol ((char *)ptr, NULL, 0);
  604.     }
  605.  
  606.     if (c)
  607.     {
  608.     if (Current[ep->column] == 0)
  609.     {
  610.         Clen = ep->column + 1;
  611.         Current[Clen] = 0;
  612.     }
  613.  
  614.     if (!Nsu && Current[ep->column] != c)
  615.     {
  616.         LINE text_line;
  617.  
  618.         ep->modified = TRUE;    /* Text has been modified */
  619.  
  620.         Current[ep->column] = c;    /* Change char */
  621.  
  622.         /* get the actual line */
  623.         text_line = GETLINE(ep,ep->line);
  624.  
  625.         /* if the char fits into the line, just copy it (ie. avoid
  626.            text_sync(). Else call text_sync() */
  627.  
  628.         if (ep->column < LENGTH(text_line))
  629.         {
  630.         char * ptr;
  631.  
  632.         /* change it */
  633.         ptr = CONTENTS(text_line);
  634.         ptr[ep->column] = c;
  635.         }
  636.         else
  637.         text_sync ();
  638.  
  639.         /* Delete the character on screen. First, find the color
  640.            we need for this operation, then draw over it */
  641.         if (is_inblock (ep->line, ep->column) & BP_INSIDE)
  642.         SetAPen (ep->win->RPort, BLOCK_BPEN);
  643.         else
  644.         SetAPen (ep->win->RPort, TEXT_BPEN);
  645.  
  646.         /* redraw that character */
  647.         {
  648.         UWORD lin, col;
  649.  
  650.         col = ep->column - ep->topcolumn;
  651.         lin = ep->line - ep->topline;
  652.  
  653.         SetWrMsk (ep->win->RPort, 0xFF);
  654.         RectFill (ep->win->RPort, COL(col), ROW(lin),
  655.                     COL(col+1)-1, ROW(lin+1)-1);
  656.         }
  657.  
  658.         redraw_textlineseg (ep->line, ep->column, ep->column+1);
  659.     }
  660.     }
  661. } /* do_tlate */
  662.  
  663.  
  664. void do_justify (void)
  665. {
  666.     ED *ep = Ep;
  667.     WORD  firstnb, lastnb, i, n, fill, c, sp;
  668.     WORD  changed = FALSE;
  669.  
  670.     switch(av[1][0])
  671.     {
  672.     case 'c':
  673.     break;
  674.  
  675.     case 'f':
  676.         firstnb = firstns((char *)Current);
  677.         lastnb = lastns((char *)Current);
  678.         if (firstnb < lastnb && ep->config.margin < MAXLINELEN-1)
  679.         {
  680.         n = 0;
  681.         i = firstnb;
  682.         while (i <= lastnb)
  683.         {
  684.             while ((c = Current[i]) && c != ' ')
  685.             i++;
  686.             if (i <= lastnb)
  687.             {
  688.             n++;
  689.             while (Current[i] == ' ')
  690.                 i++;
  691.             }
  692.         }
  693.         fill = ep->config.margin - lastnb - 1;
  694.         i = firstnb;
  695.         Current[lastnb + 1] = 0;
  696.         if (n > 0 && fill > 0)
  697.             changed = TRUE;
  698.         while (n > 0 && fill > 0 && Current[i])
  699.         {
  700.             while ((c = Current[i]) && c != ' ')
  701.             i++;
  702.             sp = fill / n;
  703.             movmem (&Current[i], &Current[i + sp],
  704.                 strlen((char *)&Current[i]) + 1);
  705.             memset ((char *)&Current[i], ' ', sp);
  706.             while (Current[i] == ' ')
  707.             i++;
  708.             fill -= sp;
  709.             n--;
  710.         }
  711.         }
  712.     break;
  713.  
  714.     default:
  715.     break;
  716.     }
  717.  
  718.     if (changed)
  719.     {
  720.     text_sync ();
  721.     text_redisplaycurrline ();
  722.     }
  723. } /* do_justify */
  724.  
  725.  
  726. void do_unjustify (void)
  727. {
  728.     WORD  i, j, waswhite = FALSE;
  729.     UBYTE c;
  730.  
  731.     for (i = 0; Current[i] == ' '; i++);
  732.  
  733.     for (j = i; Current[i]; i++)
  734.     {
  735.     c = Current[j] = Current[i];
  736.  
  737.     if (c != ' ' || !waswhite)
  738.         j++;
  739.  
  740.     waswhite = (c == ' ');
  741.     }
  742.  
  743.     Current[j] = 0;
  744.  
  745.     if (i != j)
  746.     {
  747.     text_sync ();
  748.     text_redisplaycurrline ();
  749.     }
  750. } /* do_unjustify */
  751.  
  752.  
  753. void do_indent (void)
  754. {
  755.     Line   start,
  756.        end;
  757.     Column column;
  758.     int    indent,
  759.        dir,
  760.        align,
  761.        len,
  762.        curr_indent,
  763.        leading,
  764.        trailing,
  765.        t;
  766.     char * ptr;
  767.     RP     * rp;
  768.     LINE * linelist;
  769.  
  770.     /* decode range */
  771.     ptr = av[1];
  772.  
  773.     start = end = -1;
  774.  
  775.     while (*ptr)
  776.     {
  777.     if (*ptr == '.')
  778.     {
  779.         start = end = Ep->line;
  780.         break;
  781.     } else if (isdigit(*ptr))
  782.     {
  783.         if (start == -1)
  784.         start = atoi (ptr);
  785.         else end = atoi (ptr);
  786.  
  787.         while (isdigit(*ptr)) ptr ++;
  788.  
  789.         ptr --;
  790.     } else if (*ptr == '$')
  791.     {
  792.         if (start == -1)
  793.         start = get_pong (*ptr - '0');
  794.         else
  795.         end = get_pong (*ptr - '0');
  796.     } else if (*ptr == 'b')
  797.     {
  798.         if (!block_ok())
  799.         {
  800.         error ("indent block:\nNo block specified");
  801.         return ;
  802.         }
  803.  
  804.         if (!ptr[1])
  805.         {
  806.         start = ActualBlock.start_line;
  807.         end = ActualBlock.end_line;
  808.         } else
  809.         {
  810.         ptr ++;
  811.  
  812.         if (*ptr == 's')
  813.             indent = ActualBlock.start_line;
  814.         else
  815.             indent = ActualBlock.end_line;
  816.  
  817.         if (start == -1)
  818.             start = indent;
  819.         else
  820.             end = indent;
  821.         }
  822.     } else if (*ptr == 't')
  823.     {
  824.         start = 1;
  825.         end = Ep->lines;
  826.     } else if (*ptr == '_')
  827.     {
  828.         if (start == -1)
  829.         start = Ep->lines;
  830.         else
  831.         end = Ep->lines;
  832.     }
  833.  
  834.     ptr ++;
  835.     } /* while (*ptr) */
  836.  
  837.     if (start == -1)
  838.     {
  839.     error ("indent:\ncannot evaluate start-line");
  840.     return ;
  841.     }
  842.  
  843.     if (end == -1) end = start;
  844.  
  845.     if (start > end)
  846.     {
  847.     start ^= end;        /* Swap ! 8-O */
  848.     end   ^= start;
  849.     start ^= end;
  850.     }
  851.  
  852.     /* Now find out how to indent */
  853.  
  854.     ptr = av[2];
  855.  
  856.     dir = 1;        /* indent, i.e. insert spaces */
  857.     align = 0;        /* just insert `indent' spaces */
  858.     indent = -1;
  859.     column = 0;
  860.  
  861.     while (*ptr)
  862.     {
  863.     if (*ptr == '-')
  864.         dir = -1;        /* outdent line, i.e. delete spaces */
  865.     else if (*ptr == '.')
  866.         align = 1;        /* align line to a multiple of `indent' */
  867.     else if (*ptr == 't')
  868.         indent = Ep->config.tabstop;
  869.     else if (isdigit(*ptr))
  870.     {
  871.         indent = atoi (ptr);
  872.  
  873.         while (isdigit(*ptr)) ptr++;
  874.         ptr --;
  875.     } else if (*ptr == 'c')
  876.         column = Ep->column;
  877.  
  878.     ptr ++;
  879.     } /* while (*ptr) */
  880.  
  881.     if (indent == -1)
  882.     {
  883.     error ("indent:\nCannot evaluate indent-amount");
  884.     return ;
  885.     }
  886.  
  887.     text_sync ();
  888.  
  889.     /* Note : If the line contains less spaces than indent specifies and
  890.        the user wants to outdent, the line is left-aligned, i.e. no chars
  891.        except spaces are deleted ! This is also true for indent, i.e. no
  892.        chars are moved over the right border (MAXLINELEN chars). */
  893.  
  894.     linelist = Ep->list + start;
  895.  
  896.     for (t=start; t <= end; t ++, linelist ++)
  897.     {
  898.     strcpy (Current, linelist[0]);
  899.     Clen = strlen (Current);
  900.  
  901.     if (Clen <= column) continue;
  902.  
  903.     ptr = Current + column;
  904.  
  905.     while (*ptr == ' ') ptr ++;
  906.  
  907.     if (!*ptr) continue;          /* Empty line */
  908.  
  909.     leading  = (int)ptr - (int)Current;
  910.     trailing = MAXLINELEN-1 - Clen;
  911.  
  912.     /* Should I align the line to a multiple of indent or just
  913.         insert/delete indent spaces ? */
  914.     if (align)
  915.     {
  916.         /* use appropriate difference */
  917.         if (dir > 0)
  918.         curr_indent = indent - (leading % indent);
  919.         else
  920.         {
  921.         curr_indent = leading % indent;
  922.  
  923.         if (!curr_indent)
  924.             curr_indent = indent;
  925.         }
  926.     } else curr_indent = indent;
  927.  
  928.     len = strlen (ptr) + 1;
  929.  
  930.     if (dir > 0)
  931.     {
  932.         if (trailing < curr_indent)
  933.         curr_indent = trailing;
  934.  
  935.         if (!curr_indent) continue;
  936.  
  937.         movmem (ptr, ptr+curr_indent, len);
  938.         setmem (ptr, curr_indent, ' ');
  939.     } else
  940.     {
  941.         if (leading < curr_indent)
  942.         curr_indent = leading;
  943.  
  944.         if (!curr_indent) continue;
  945.  
  946.         movmem (ptr, ptr-curr_indent, len);
  947.     }
  948.  
  949.     Clen = strlen (Current);
  950.     /* len    = strlen (linelist[0]); dead assign */
  951.  
  952. #ifdef DEBUG
  953. printf ("Old len %d  New Len %d     BlenOld %d  BlenNew %d\n",
  954.     len, Clen, ((len + 8) & ~7), ((Clen + 8) & ~7));
  955. #endif
  956.  
  957.     /* Find out if we have to allocate new memory */
  958.     /* Clen is total length in bytes while len is only strlen() */
  959.     /* TODO: Ain't work yet */
  960.     /*if ((((Clen + 8) & ~7) != ((len + 8) & ~7)))
  961.     {*/
  962.         ptr = allocline (Clen + 1);
  963.  
  964.         if (!ptr)
  965.         {
  966.         nomemory ();
  967.         /* globalflags.Abortcommand = 1; dead assign */
  968.         break;
  969.         }
  970.  
  971.         freeline (linelist[0]);
  972.         linelist[0] = ptr;
  973.     /*}*/
  974.  
  975.     strcpy (ptr, Current);
  976.     } /* for (t = start; t <= end; t ++, linelist ++) */
  977.  
  978.     Ep->modified = 1;
  979.  
  980.     text_load ();
  981.  
  982.     /* Don't display if there is nothing to display */
  983.     if (end < Ep->topline)
  984.     return;
  985.  
  986.     if (start < Ep->topline)
  987.     {
  988.     start = 0;
  989.     t = end - Ep->topline +1;
  990.     }
  991.     else
  992.     {
  993.     t = end - start +1;
  994.     start -= Ep->topline;
  995.  
  996.     if (start >= Lines)
  997.         return;
  998.     }
  999.  
  1000.     if (start+t > Lines)
  1001.     t = Lines-start;
  1002.  
  1003.     if (!Nsu)
  1004.     {
  1005.     rp = Ep->win->RPort;
  1006.  
  1007.     end = start + t-1;
  1008.  
  1009.     /* only clear area, if there is a line outside the block */
  1010.     if (!is_inblock (start + Ep->topline, -1) ||
  1011.         !is_inblock (end + Ep->topline, -1))
  1012.     {
  1013.         SetAPen (rp, TEXT_BPEN);
  1014.         SetWrMsk (rp, BLOCK_MASK);
  1015.         RectFill (rp, Xbase, ROW(start), Xpixs, ROW(start+t)-1);
  1016.     }
  1017.  
  1018.     if (!text_sync ())
  1019.         text_displayseg (start, t);
  1020.     }
  1021. } /* do_indent */
  1022.  
  1023.  
  1024. void do_inslines (void)
  1025. {
  1026.      int lines = atoi (av[1]);
  1027.  
  1028.      if (lines <= 0) return;
  1029.  
  1030.      while (lines)
  1031.      {
  1032.       do_insline ();
  1033.       lines --;
  1034.      }
  1035.  
  1036. } /* do_inslines */
  1037.  
  1038.  
  1039. void do_delete (void)
  1040. {
  1041.     char * ptr, * hptr;
  1042.  
  1043.     hptr = ptr = Current + Ep->column;
  1044.  
  1045.     if (!*hptr)
  1046.     return;
  1047.  
  1048.     if (*hptr == ' ')
  1049.     while (*hptr == ' ') hptr ++;
  1050.     else
  1051.     while (*hptr != ' ') hptr ++;
  1052.  
  1053.     memmove (ptr, hptr, strlen (hptr)+1);
  1054.  
  1055.     text_sync ();
  1056.     text_redisplaycurrline ();
  1057. } /* do_delete */
  1058.  
  1059.  
  1060. void do_delines (void)
  1061. {
  1062.      int t;
  1063.  
  1064.      t = atoi (av[1]);
  1065.  
  1066.      for ( ; t >= 0; t--)
  1067.       do_deline ();
  1068. } /* do_delines */
  1069.  
  1070.  
  1071. /*
  1072.  *  Commands submitted by Markus Wenzel
  1073.  */
  1074.  
  1075. void do_undeline (void)
  1076. {
  1077.    do_insline ();
  1078.    text_load ();
  1079.  
  1080.    strcpy((char *)Current, (char *)Deline);
  1081.  
  1082.    text_sync ();
  1083.    text_displayseg (Ep->line - Ep->topline, 1);
  1084. } /* do_undeline */
  1085.  
  1086.  
  1087. void do_clipins (void)
  1088. {
  1089.     struct IOClipReq * ior;
  1090.     struct cbbuf * buf;
  1091.     LONG    lines;
  1092.     BOOL    failed = 0;
  1093.     ED      * ep       = Ep;
  1094.  
  1095.     if (!(ior = CBOpen (0)) )
  1096.     return;
  1097.  
  1098.     if (CBQueryFTXT (ior))
  1099.     {
  1100.     buf = CBReadCHRS (ior);
  1101.  
  1102.     if (buf)
  1103.     {
  1104.         UBYTE line[MAXLINELEN];
  1105.         UBYTE * ptr1, * ptr2;
  1106.         LINE ptr;
  1107.         int len;
  1108.  
  1109.         ptr2 = line;
  1110.         ptr1 = buf->mem;
  1111.  
  1112.         while (*ptr1 && *ptr1 != '\n')
  1113.         *ptr2 ++ = *ptr1 ++;
  1114.  
  1115.         *ptr2 = 0;
  1116.  
  1117.         text_write (line);
  1118.  
  1119.         if (*ptr1)
  1120.         {
  1121.         do_split ();
  1122.         do_down ();
  1123.         do_firstcolumn ();
  1124.  
  1125.         lines = ep->lines;
  1126.  
  1127.         for (ptr1 ++; *ptr1; )
  1128.         {
  1129.             ptr2 = line;
  1130.             len = 0;
  1131.  
  1132.             while (*ptr1 && *ptr1 != '\n')
  1133.             {
  1134.             *ptr2 ++ = *ptr1 ++;
  1135.             len ++;
  1136.             }
  1137.  
  1138.             *ptr2 = 0;
  1139.             len ++;
  1140.  
  1141.             if (*ptr1)
  1142.             ptr1 ++;
  1143.             else
  1144.             {
  1145.             text_write (line);
  1146.             break;
  1147.             }
  1148.  
  1149.             if (makeroom(256) && (ptr = allocline(len)))
  1150.             {
  1151.             SETLINE(ep,ep->lines,ptr);
  1152.             ep->lines ++;
  1153.  
  1154.             movmem(line, ptr, len);
  1155.             }
  1156.             else
  1157.             {
  1158.             set_window_params ();
  1159.             nomemory ();
  1160.             failed = 1;
  1161.             break;
  1162.             }
  1163.         }
  1164.  
  1165.         if (!failed && lines <= ep->lines - 1)
  1166.         {
  1167.             /* INSFILE: move text to correct position */
  1168.             ActualBlock.ep       = ep;
  1169.             ActualBlock.start_line = lines;
  1170.             ActualBlock.end_line   = ep->lines - 1;
  1171.             ActualBlock.type       = BT_LINE;
  1172.  
  1173.             do_bmove ();
  1174.         }
  1175.         } /* more than one line */
  1176.  
  1177.         window_title ();
  1178.  
  1179.         CBFreeBuf (buf);
  1180.     }
  1181.  
  1182.     CBReadDone (ior);
  1183.     }
  1184.  
  1185.     CBClose (ior);
  1186. } /* do_clipins */
  1187.  
  1188.  
  1189. void do_space (void)
  1190. {
  1191.     ED * ep = Ep;
  1192.     int  insmode = ep->config.insertmode;
  1193.  
  1194.     ep->config.insertmode = 1;
  1195.     text_write (" ");
  1196.     ep->config.insertmode = insmode;
  1197. } /* do_space */
  1198.  
  1199.  
  1200. void do_return (void)
  1201. {
  1202.     char   buf[MAXLINELEN];
  1203.     char * partial;
  1204.  
  1205.     if (globalflags.Comlinemode)
  1206.     {
  1207.     strcpy (buf, (char *)Current);
  1208.  
  1209.     partial = esc_partial;    /* PATCH_NULL: P -> esc_p */
  1210.     esc_partial = NULL;    /* PATCH_NULL: P -> esc_p */
  1211.  
  1212.     escapecomlinemode ();
  1213.  
  1214.     if (partial)
  1215.     {
  1216.         if (do_command (buf))
  1217.         do_command (partial);
  1218.  
  1219.         free(partial);
  1220.     } else
  1221.         do_command (buf);
  1222.     } else
  1223.     {
  1224.     if (Ep->config.autoindent)
  1225.     {   /* If user want's autoindent */
  1226.         WORD   indent;  /* how much */
  1227.         WORD   line;    /* Line-no. */
  1228.         char * ptr;     /* pointer to Ep->list[line] */
  1229.  
  1230.         text_sync ();   /* store actual line */
  1231.  
  1232.         /* Start with current line */
  1233.         indent = 0;
  1234.         ptr = (char *)Current;
  1235.  
  1236.         /* Find 1. nonspace ... */
  1237.         while (isspace (*ptr))
  1238.         {
  1239.         ptr ++;
  1240.         indent ++;
  1241.         }
  1242.  
  1243.         /* ... but not '\0'. In this case the line is empty and
  1244.            indent is therefore 0 */
  1245.         if (!*ptr)
  1246.         indent = 0;
  1247.  
  1248.         /* Try on, if indent is zero, line is empty and there are more
  1249.            lines on top */
  1250.         if (!indent && !*ptr && Ep->line)
  1251.         {
  1252.         line = Ep->line - 1;
  1253.  
  1254.         /* Until 1. line */
  1255.         while (line)
  1256.         {
  1257.             /* Try every line */
  1258.             ptr = GETTEXT(Ep,line);
  1259.             indent = 0;
  1260.  
  1261.             while (isspace (*ptr))
  1262.             {
  1263.             ptr ++;
  1264.             indent ++;
  1265.             }
  1266.  
  1267.             if (indent || *ptr)
  1268.             break;
  1269.  
  1270.             line --;
  1271.         }
  1272.         }
  1273.  
  1274.         /* Not at last position in line ? then we have to split and
  1275.            indent the rest */
  1276.         if (Ep->column != Clen)
  1277.         {
  1278.         /* Split line, move to next line but shouldn't show this */
  1279.         do_split ();
  1280.         do_down ();
  1281.  
  1282.         /* Indent new line */
  1283.         if (indent > Ep->column)
  1284.             indent -= indent - Ep->column;
  1285.  
  1286.         if (indent > 0)
  1287.         {
  1288.             movmem (Current, Current+indent, Clen+1);
  1289.             setmem (Current, indent, ' ');
  1290.             Clen += indent;
  1291.             Ep->column = indent;
  1292.         } else
  1293.             Ep->column = 0;
  1294.  
  1295.         Current[Clen] = 0;
  1296.  
  1297.         /* and position cursor */
  1298.         text_sync ();
  1299.  
  1300.         /* Show result */
  1301.         text_redisplaycurrline ();
  1302.         } else
  1303.         {
  1304.         if (Ep->line != Ep->lines-1)
  1305.         {
  1306.             do_down ();
  1307.             do_insline ();
  1308.  
  1309.             Ep->column = indent;
  1310.             text_sync ();
  1311.         } else
  1312.         {
  1313.             do_split ();
  1314.             Ep->column = indent;
  1315.             text_sync ();
  1316.             do_down ();
  1317.         }
  1318.         }
  1319.     } else
  1320.     {
  1321.         Ep->column = 0;
  1322.         text_sync ();
  1323.         do_downadd ();
  1324.     }
  1325.     } /* !Comlinemode */
  1326. } /* do_return */
  1327.  
  1328.  
  1329. /******************************************************************************
  1330. *****  ENDE edit.c
  1331. ******************************************************************************/
  1332.